﻿using System;
using System.Collections;
using System.Collections.Generic;

using Gonte.Collections;

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace MyUtilitiesTest
{
    /// <summary>
    ///This is a test class for StringKeyDictionaryTest and is intended
    ///to contain all StringKeyDictionaryTest Unit Tests
    ///</summary>
    [TestClass()]
    public class StringKeyDictionaryTest
    {
        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        public static void ChangeValue(Object sender, AfterInsertEventArgs args)
        {
            StringKeyDictionary<String> dictionary = (StringKeyDictionary<String>)sender;
            String key = (String)args.Key;
            dictionary[key] = "B"; // Change the value to B
            String value = (String)args.Value;
        }

        [TestMethod()]
        public void StringKeyDictionaryAddTest()
        {
            StringKeyDictionary<String> dictionary = new StringKeyDictionary<String>(10);
            dictionary.AfterInsert += new StringKeyDictionary<String>.AfterInsertHandler(StringKeyDictionaryTest.ChangeValue);
            String key = "A";
            String value = "A";
            dictionary.Add(key, value);

            Assert.IsTrue(dictionary.ContainsKey("A"));
            Assert.AreEqual("B", dictionary["A"]); // The value was changed by the event handler

            foreach (String s in dictionary.Values)
            {
                Assert.AreEqual("B", s);
            }
            Assert.AreEqual(1, dictionary.Count);
        }

        [TestMethod()]
        [ExpectedException(typeof(ArgumentException))]
        public void StringKeyDictionaryAddRepeatedItemTest()
        {
            StringKeyDictionary<String> dictionary = new StringKeyDictionary<String>();
            dictionary.Add("A", "A");
            dictionary.Add("A", "A2");
        }

        public static void UpdateIfDuplicate(Object sender, RepeatedItemEventArgs args)
        {
            StringKeyDictionary<String> dictionary = (StringKeyDictionary<String>)sender;
            String key = (String)args.Key;
            dictionary[key] = (String)args.Value;
        }

        [TestMethod()]
        public void StringKeyDictionaryAddRepeatedItemWithEventHandlingTest()
        {
            StringKeyDictionary<String> dictionary = new StringKeyDictionary<String>();
            dictionary.RepeatedItem += new StringKeyDictionary<String>.RepeatedItemHandler(StringKeyDictionaryTest.UpdateIfDuplicate);
            dictionary.Add("A", "A");
            dictionary.Add("A", "A2");

            Assert.AreEqual(1, dictionary.Count);
            Assert.AreEqual("A2", dictionary["A"]); // The value was updated by the event handler

        }

        [TestMethod()]
        public void StringKeyDictionaryRemoveTest()
        {
            StringKeyDictionary<String> dictionary = new StringKeyDictionary<String>();
            String key = "A";
            String value = "A";
            dictionary.Add(key, value);

            dictionary.Remove("A"); // It is case insensitive

            Assert.IsFalse(dictionary.ContainsKey("A"));
        }

        [TestMethod()]
        [ExpectedException(typeof(KeyNotFoundException))]
        public void StringKeyDictionaryLookupNonExistentItemTest()
        {
            StringKeyDictionary<String> dictionary = new StringKeyDictionary<String>();
            String value = dictionary["A"];
        }

        public static void AddValue(Object sender, ItemNotFoundEventArgs args)
        {
            StringKeyDictionary<String> dictionary = (StringKeyDictionary<String>)sender;
            String key = (String)args.Key;
            dictionary[key] = "C";
        }

        [TestMethod()]
        public void StringKeyDictionaryLookupNonExistentItemWithEventHandlerTest()
        {
            StringKeyDictionary<String> dictionary = new StringKeyDictionary<String>();
            dictionary.ItemNotFound += new StringKeyDictionary<String>.ItemNotFoundHandler(StringKeyDictionaryTest.AddValue);
            String value = dictionary["A"];

            Assert.AreEqual(1, dictionary.Count);
            Assert.AreEqual("C", value); // The value was updated by the event handler
        }

        [TestMethod()]
        [ExpectedException(typeof(KeyNotFoundException))]
        public void StringKeyDictionaryRemoveNonExistentItemTest()
        {
            StringKeyDictionary<String> dictionary = new StringKeyDictionary<String>();
            dictionary.Remove("A");
        }

        [TestMethod()]
        public void StringKeyDictionaryRemoveNonExistentItemWithEventHandlerTest()
        {
            StringKeyDictionary<String> dictionary = new StringKeyDictionary<String>();
            dictionary.ItemNotFound += new StringKeyDictionary<String>.ItemNotFoundHandler(StringKeyDictionaryTest.AddValue);
            dictionary.Remove("A");

            Assert.AreEqual(0, dictionary.Count);
        }

        public static void AddHistory(Object sender, BeforeRemoveEventArgs args)
        {
            StringKeyDictionary<String> dictionary = (StringKeyDictionary<String>)sender;
            String key = (String)args.Key;
            dictionary["H"] = (String)args.Value;
        }

        [TestMethod()]
        public void StringKeyDictionaryRemoveItemWithBeforeRemoveEventHandlerTest()
        {
            StringKeyDictionary<String> dictionary = new StringKeyDictionary<String>();
            dictionary.BeforeRemove += new StringKeyDictionary<String>.BeforeRemoveHandler(StringKeyDictionaryTest.AddHistory);
            dictionary["A"] = "A value";
            dictionary.Remove("A");

            Assert.AreEqual(1, dictionary.Count);
            Assert.AreEqual("A value", dictionary["H"]); // The value was updated by the event handler
        }

        [TestMethod()]
        public void StringKeyDictionaryIDictionaryTest()
        {
            IDictionary dictionary = new StringKeyDictionary<String>();
            dictionary["A"] = "A value";

            Assert.AreEqual(1, dictionary.Count);
            Assert.AreEqual("A value", dictionary["A"]);

            dictionary.Clear();
            Assert.AreEqual(0, dictionary.Count);

            dictionary.Add("A", "A new value");
            Assert.IsTrue(dictionary.Contains("A"));

            foreach (String key in dictionary.Keys)
            {
                Assert.AreEqual("A new value", dictionary[key]);
            }

            foreach (String val in dictionary.Values)
            {
                Assert.AreEqual("A new value", val);
            }
            dictionary.Remove("A");
            Assert.AreEqual(0, dictionary.Count);

            dictionary["A"] = "A";
            dictionary["B"] = "B";
            dictionary["C"] = "C";

            String[] array = new String[dictionary.Count];
            dictionary.CopyTo(array, 0);

            Assert.AreEqual("A", array[0]);
            Assert.AreEqual("B", array[1]);
            Assert.AreEqual("C", array[2]);

            Assert.AreEqual(false, dictionary.IsReadOnly);
            Assert.AreEqual(false, dictionary.IsFixedSize);
        }

        [TestMethod()]
        public void StringKeyDictionaryFindTest()
        {
            StringKeyDictionary<String> dictionary = new StringKeyDictionary<String>();
            dictionary["A"] = "AAA";
            dictionary["B"] = "BBB";
            dictionary["C"] = "CCC";
            String b = dictionary.Find("BBB", delegate(String item, Object obj) 
                              {
                                  return item.Equals(obj.ToString());
                              });

            Assert.AreEqual("BBB", b);
        }

        [TestMethod()]
        public void StringKeyDictionaryFindNotFoundTest()
        {
            StringKeyDictionary<String> dictionary = new StringKeyDictionary<String>();
            dictionary["A"] = "AAA";
            dictionary["B"] = "BBB";
            dictionary["C"] = "CCC";
            String b = dictionary.Find("DDD", delegate(String item, Object obj)
            {
                return item.Equals(obj.ToString());
            });

            Assert.AreEqual(null, b);
        }

        [TestMethod()]
        public void StringKeyDictionaryFindAllTest()
        {
            StringKeyDictionary<String> dictionary = new StringKeyDictionary<String>();
            dictionary["A"] = "AAA";
            dictionary["B"] = "BBB";
            dictionary["C"] = "CCC";
            dictionary["D"] = "AAA";
            List<String> found = dictionary.FindAll("AAA", delegate(String item, Object obj)
            {
                return item.Equals(obj.ToString());
            });

            Assert.AreEqual(2, found.Count);
        }

        [TestMethod()]
        public void StringKeyDictionaryFindAllNotFoundTest()
        {
            StringKeyDictionary<String> dictionary = new StringKeyDictionary<String>();
            dictionary["A"] = "AAA";
            dictionary["B"] = "BBB";
            dictionary["C"] = "CCC";
            dictionary["D"] = "AAA";
            List<String> found = dictionary.FindAll("DDD", delegate(String item, Object obj)
            {
                return item.Equals(obj.ToString());
            });

            Assert.AreEqual(0, found.Count);
        }

        [TestMethod()]
        public void StringKeyDictionaryIDictionaryGetEnumeratorTest()
        {
            IDictionary dictionary = new StringKeyDictionary<String>();
            Assert.IsNotNull(dictionary.GetEnumerator());
        }

        [TestMethod()]
        public void StringKeyDictionaryIDictionaryIEnumerableGetEnumeratorTest()
        {
            IEnumerable enumerable = new StringKeyDictionary<String>();
            Assert.IsNotNull(enumerable.GetEnumerator());
        }

        [TestMethod()]
        public void StringKeyDictionaryIDictionaryIsSynchronizedTest()
        {
            IDictionary dictionary = new StringKeyDictionary<String>();
            Assert.IsFalse(dictionary.IsSynchronized);
        }

        [TestMethod()]
        public void StringKeyDictionaryIDictionarySyncRootTest()
        {
            IDictionary dictionary = new StringKeyDictionary<String>();
            Assert.IsNotNull(dictionary.SyncRoot);
        }
    }
}
